/*//////////////////////////////////////////////////////////////////////////////
//
//                  INTEL CORPORATION PROPRIETARY INFORMATION
//     This software is supplied under the terms of a license agreement or
//     nondisclosure agreement with Intel Corporation and may not be copied
//     or disclosed except in accordance with the terms of that agreement.
//          Copyright(c) 2002-2007 Intel Corporation. All Rights Reserved.
//
*/

#include "umc_defs.h"
#if defined (UMC_ENABLE_MP3_INT_AUDIO_ENCODER)

#include "mp3enc_own_int.h"

#define LEN_MDCT_LINE  576
#define SF_OFFSET      210
#define MAX_QUANT      8206
#define MAGIC_NUMBER_I 26568
#define QUANT_ITER_NUM 8

#define C_0_95_Q15 31129
#define C_0_85_Q15 27852
#define C_1_2_Q14  19660
#define C_0_2_Q15  6553
#define C_0_5_Q15  16384
#define C_0_6_Q15  19660

void mp3ienc_quantCalcAvailableBits(MP3Enc *state) {
    Ipp32s ch, gr;
    Ipp32s len;
    Ipp32s bitsPerFrame;
    Ipp32s mean_bits;
    Ipp32s bits_in_buf, max_bits_in_buf;
    Ipp32s bits_from_buffer, com_additional_bits;
    Ipp32s additional_bits[2][2];
//  Ipp32s up, l;
    Ipp32s div;
    IppMP3FrameHeader *header = &state->com.header;
    Ipp32s stereo = state->com.stereo;
    Ipp32s ms = state->com.stereo_mode == MPA_MS_STEREO ? 2 : 0;

    len = 32;   // header

    if (stereo == 1)
        len += 136;
    else
        len += 256;

    if (header->protectionBit)
        len += 16;

    state->com.frameBits = len;
    bitsPerFrame = state->com.slot_size << 3;

    max_bits_in_buf = 8*511;
    mean_bits = (bitsPerFrame - len);
    bits_in_buf = state->com.si_main_data_begin * 8;

    if (mp3_bitrate[header->id][header->layer-1][header->bitRate] != 320) {
        if (state->com.br_mode == MPAENC_ABR) {
          Ipp32s br_ind;

          bits_from_buffer = state->com.bytes_in_gbuf << 3;

          if (bits_from_buffer < state->com.slot_size * MAX_GBUF_COEF)
            mean_bits = C_0_85_Q15 * mean_bits >> 15;

          br_ind = mp3encLEBitrate(&state->com, (bitsPerFrame + bits_from_buffer) >> 3);

          bits_from_buffer =
            (state->com.slot_sizes[br_ind] - state->com.slot_size +
            state->com.si_main_data_begin) << 3;
        } else {
          if (bits_in_buf > (C_0_95_Q15 * max_bits_in_buf >> 15)) {
            bits_from_buffer = (C_0_95_Q15 * max_bits_in_buf >> 15);
            mean_bits += bits_in_buf - (C_0_95_Q15 * max_bits_in_buf >> 15);
          } else {
            bits_from_buffer = bits_in_buf;
          }
          mean_bits = C_0_85_Q15 * mean_bits >> 15;
        }

        mean_bits >>= stereo;

        com_additional_bits = 0;

        for (gr = 0; gr < 2; gr++) {
            for (ch = 0; ch < stereo; ch++) {
                Ipp32s pe = state->ipa_curr_frame_PE_st[gr][ch+ms] - 1000;
                if (pe > 32767) pe = 32767;

                additional_bits[gr][ch] = pe * C_0_6_Q15 >> 15;

                if (additional_bits[gr][ch] < 0) {
                    additional_bits[gr][ch] = 0;
                }
                if (state->com.si_blockType[gr][ch] != NORM_TYPE) {
                    if (additional_bits[gr][ch] * 2 < mean_bits)
                        additional_bits[gr][ch] = mean_bits >> 1;
                    else if (additional_bits[gr][ch] > (C_1_2_Q14 * mean_bits >> 14))
                        additional_bits[gr][ch] = (C_1_2_Q14 * mean_bits >> 14);
                } else {
                  Ipp32s max_add_bits;
                  if (state->com.br_mode == MPAENC_ABR)
                    max_add_bits = (C_0_5_Q15 * mean_bits >> 15);
                  else
                    max_add_bits = (C_0_2_Q15 * mean_bits >> 15);
                  if (additional_bits[gr][ch] > max_add_bits)
                    additional_bits[gr][ch] = max_add_bits;
                }

                com_additional_bits += additional_bits[gr][ch];
            }
        }

        if (com_additional_bits > bits_from_buffer && com_additional_bits)
            div = bits_from_buffer * 32768 / com_additional_bits;
        else
            div = 0;

        for (gr = 0; gr < 2; gr++) {
            for (ch = 0; ch < stereo; ch++) {
                if (com_additional_bits > bits_from_buffer) {
                    additional_bits[gr][ch] = additional_bits[gr][ch] * div >> 15;
                }

                state->com.max_bits[gr][ch] =
                    mean_bits + additional_bits[gr][ch];
            }
        }
        for (gr = 0; gr < 2; gr++) {
          if (state->com.stereo_mode == MPA_MS_STEREO) {
            Ipp32s add_bits;
            if (state->ms_dcoef[gr] == 0)
              add_bits = 0;
            else {
              ippsDiv_32s_Sfs(&state->ms_dcoef[gr], &state->ms_ncoef[gr], &add_bits, 1, -15);
              add_bits = 3 * state->com.max_bits[gr][1] * (add_bits - 16384) >> 16;
            }

            if (add_bits < 0) add_bits = 0;
            state->com.max_bits[gr][0] += add_bits;
            state->com.max_bits[gr][1] -= add_bits;
          }
        }
    } else {
        mean_bits += bits_in_buf;
        mean_bits >>= stereo;
        for (gr = 0; gr < 2; gr++)
            for (ch = 0; ch < stereo; ch++)
                state->com.max_bits[gr][ch] = mean_bits;
    }
    for (gr = 0; gr < 2; gr++)
      for (ch = 0; ch < stereo; ch++)
        if (state->com.max_bits[gr][ch] > 4095)
          state->com.max_bits[gr][ch] = 4095;
}

static Ipp16s scalefac_pow[] = {
  32767, 18658, 21247, 24196, 27554, 31379, 17867, 20347,
  23170, 26386, 30048, 17109, 19484, 22188, 25268, 28774
};

static Ipp16s scalefac_pow_shift[] = {
  0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3
};

/*******************************************************************/

static Ipp32s mp3ienc_AdjustSF(MP3Enc *state, Ipp32s *xmin_,
                               Ipp32s *distortion, Ipp32s *sfb_last, Ipp32s gr, Ipp32s ch,
                               Ipp32s mdct_scaleFactor, Ipp32s *pow34_scaleFact)
{
  Ipp32s i, sfb, width, pos, wnd;
  Ipp32u *sfb_long, *sfb_short;
  Ipp16s sf_tmp_16s;
  Ipp32s sf_tmp, scl;
  Ipp64s noise64;
  Ipp32s noise, xmin;
  Ipp16s ifqstep;
  Ipp32s dist_max, dist;
  Ipp32s ret_flag = 0;
  Ipp32s sf_glob;
  Ipp16s dist_max16;
  Ipp16s scaled_max;

  Ipp32s *mdct_line_abs = state->mdct_line_abs_int;
  Ipp16s *mdct_scaled_short = state->mdct_scaled_short;
  Ipp32s *mdct_rqnt = state->mdct_rqnt;
  Ipp16u scalefac_l_save[32];
  Ipp16u scalefac_s_save[12][3];

  sfb_long = mp3enc_sfBandIndex[state->com.header.id][state->com.header.samplingFreq].l;
  sfb_short = mp3enc_sfBandIndex[state->com.header.id][state->com.header.samplingFreq].s;

  if (state->com.si_sfScale[gr][ch] == 0) {
    ifqstep = 21247;
    scaled_max = 25266;
  } else {
    ifqstep = 27554;
    scaled_max = 19483;
  }

  scl = -2 - 2 * (Ipp16s)state->com.si_sfScale[gr][ch];
  sf_glob = state->com.si_globGain[gr][ch] - 106;

  if (state->com.si_blockType[gr][ch] != 2) {
    for (sfb = 0, pos = 0; sfb < state->com.sfb_l_max; sfb++, pos+=width) {
      scalefac_l_save[sfb] = state->com.scalefac_l[gr][ch][sfb];

      width = sfb_long[sfb+1] - sfb_long[sfb];
      noise = 0;

      if (state->com.si_preFlag[gr][ch] == 0)
        sf_tmp = scl * state->com.scalefac_l[gr][ch][sfb];
      else
        sf_tmp = scl * (state->com.scalefac_l[gr][ch][sfb]/* + pretab[sfb]*/);

      sf_tmp += sf_glob;

      if (sf_tmp == sfb_last[sfb])
        continue;
      sfb_last[sfb] = sf_tmp;

      sf_tmp_16s = (Ipp16s)sf_tmp;

      ippsPow43Scale_16s32s_Sf(state->com.quant_ix[gr][ch] + pos - sfb_long[sfb],
          mdct_rqnt + pos - sfb_long[sfb],
          &sf_tmp_16s, (const Ipp32s *)(sfb_long + sfb),0,1,1,0);

      noise64 = 0;

      for (i = 0; i < width; i++) {
        Ipp32s temp;
        temp = mdct_line_abs[pos+i] - mdct_rqnt[pos+i];
        noise64 += temp * (Ipp64s)temp;
      }
      if (2 * mdct_scaleFactor + 8 > 0)
        noise = (Ipp32s)(noise64 >> (2 * mdct_scaleFactor + 8));
      else
        noise = (Ipp32s)(noise64 << -(2 * mdct_scaleFactor + 8));

      xmin = xmin_[sfb];
      dist = 0;
      if (xmin > 0)
        ippsDiv_32s_Sfs(&xmin, &noise, &dist, 1, -22);

      distortion[sfb] = dist;
    }

    ippsMax_32s(distortion, state->com.sfb_l_max, &dist_max);

    ippsSqrt_32s16s_Sfs(&dist_max, &dist_max16, 1, 0);
    dist_max = dist_max16 << 11;

    if (dist_max >= (1 << 22)) {
      pos = 0;
      for (sfb = 0; sfb < state->com.sfb_l_max; sfb++) {
        Ipp16s sca_min16, sca_max16;
        Ipp32s sca_min, sca_max;
        width = sfb_long[sfb+1] - sfb_long[sfb];

        if (distortion[sfb] > dist_max)
        {
          Ipp32s s = state->com.scalefac_l[gr][ch][sfb];
          if (s < 3) {
            state->com.scalefac_l[gr][ch][sfb] = (Ipp16u)(s + 1);
            ippsMinMax_16s(mdct_scaled_short + pos, width, &sca_min16, &sca_max16);
            sca_min = -((Ipp32s)sca_min16);
            sca_max = sca_max16;

            if (sca_min > sca_max) {
              sca_max = sca_min - 1;
            }

            if (sca_max >= scaled_max) {
              *pow34_scaleFact = *pow34_scaleFact + 1;
              ippsRShiftC_16s_I(1, mdct_scaled_short, 576);
            }
            ippsMulC_16s_ISfs(ifqstep, mdct_scaled_short + pos, width, 14);

            ret_flag = 1;
          }
        }
        pos += width;
      }
    }
  } else {
    for (sfb = 0, pos = 0; sfb < state->com.sfb_s_max; sfb++) {
      width = sfb_short[sfb+1] - sfb_short[sfb];

      for (wnd = 0; wnd < 3; wnd++, pos += width) {
        scalefac_s_save[sfb][wnd] = state->com.scalefac_s[gr][ch][sfb][wnd];
        noise = 0;

        if (state->com.si_preFlag[gr][ch] == 0)
          sf_tmp = scl * state->com.scalefac_s[gr][ch][sfb][wnd];
        else
          sf_tmp = scl * (state->com.scalefac_s[gr][ch][sfb][wnd]/* + pretab[sfb]*/);

        sf_tmp += sf_glob;

        if (sf_tmp == sfb_last[sfb*3+wnd])
          continue;

        sfb_last[sfb*3+wnd] = sf_tmp;

        sf_tmp_16s = (Ipp16s)sf_tmp;

        ippsPow43Scale_16s32s_Sf(state->com.quant_ix[gr][ch] + pos - sfb_short[sfb],
          mdct_rqnt + pos - sfb_short[sfb],
          &sf_tmp_16s, (const Ipp32s *)(sfb_short + sfb),0,1,1,0);

        noise64 = 0;

        for (i = 0; i < width; i++) {
          Ipp32s temp;
          temp = mdct_line_abs[pos+i] - mdct_rqnt[pos+i];
          noise64 += temp * (Ipp64s)temp;
        }
        if (2 * mdct_scaleFactor + 8 > 0)
          noise = (Ipp32s)(noise64 >> (2 * mdct_scaleFactor + 8));
        else
          noise = (Ipp32s)(noise64 << -(2 * mdct_scaleFactor + 8));

        xmin = xmin_[sfb*3+wnd];
        dist = 0;
        if (xmin > 0)
          ippsDiv_32s_Sfs(&xmin, &noise, &dist, 1, -22);

        distortion[sfb*3+wnd] = dist;

      }
    }
    ippsMax_32s(distortion, state->com.sfb_s_max*3, &dist_max);

    ippsSqrt_32s16s_Sfs(&dist_max, &dist_max16, 1, 0);
    dist_max = dist_max16 << 11;

    if (dist_max >= (1 << 22))
    {
      pos = 0;
      for (sfb = 0; sfb < state->com.sfb_s_max; sfb++) {
        Ipp16s sca_min16, sca_max16;
        Ipp32s sca_min, sca_max;
        width = sfb_short[sfb+1] - sfb_short[sfb];
        for (wnd = 0; wnd < 3; wnd++) {
          if (distortion[sfb*3+wnd] > dist_max)
          {
            Ipp32s s = state->com.scalefac_s[gr][ch][sfb][wnd];
            if (s < 3) {
              state->com.scalefac_s[gr][ch][sfb][wnd] = (Ipp16u)(s + 1);

              ippsMinMax_16s(mdct_scaled_short + pos, width, &sca_min16, &sca_max16);
              sca_min = -((Ipp32s)sca_min16);
              sca_max = sca_max16;

              if (sca_min > sca_max) {
                sca_max = sca_min - 1;
              }

              if (sca_max >= scaled_max) {
                *pow34_scaleFact = *pow34_scaleFact + 1;
                ippsRShiftC_16s_I(1, mdct_scaled_short, 576);
              }
              ippsMulC_16s_ISfs(ifqstep, mdct_scaled_short + pos, width, 14);

              ret_flag = 1;
            }
          }
          pos += width;
        }
      }
    }
  }

  mp3enc_quantcalcPart2Len(&state->com, gr, ch);
  if (state->com.si_part2Len[gr][ch] + state->com.si_part23Len[gr][ch] > (Ipp32u)state->com.max_bits[gr][ch]) {
    if (state->com.si_blockType[gr][ch] != 2) {
      for (sfb = 0; sfb < state->com.sfb_l_max; sfb++) {
        state->com.scalefac_l[gr][ch][sfb] = scalefac_l_save[sfb];
      }
    } else {
      for (sfb = 0; sfb < state->com.sfb_s_max; sfb++) {
        for (wnd = 0; wnd < 3; wnd++) {
          state->com.scalefac_s[gr][ch][sfb][wnd] = scalefac_s_save[sfb][wnd];
        }
      }
    }
    mp3enc_quantcalcPart2Len(&state->com, gr, ch);
    return 0;
  }

  return ret_flag;
}

Ipp32s mp3ienc_quantization(MP3Enc *state)
{
    Ipp32s gr, ch, pos, wnd, sfb;
    Ipp32u *sfb_long, *sfb_short;
    IppMP3FrameHeader *header = &state->com.header;
    Ipp32s last_frame_common_scalefactor;
    Ipp32s xmin[36], distortion[36], mdct_pwr;
    Ipp32s sfb_last[36];
    Ipp32s iter;

    Ipp32s *mdct_line_abs_int = state->mdct_line_abs_int;

    Ipp16s *mdct_line_abs_short = state->mdct_line_abs_short;
    Ipp16s *mdct_scaled_short = state->mdct_scaled_short;

    sfb_long = mp3enc_sfBandIndex[header->id][header->samplingFreq].l;
    sfb_short = mp3enc_sfBandIndex[header->id][header->samplingFreq].s;

    mp3ienc_quantCalcAvailableBits(state);

    for (gr = 0; gr < 2; gr++) {
        for (ch = 0; ch < state->com.stereo; ch++) {
            Ipp32s i;
            Ipp32s max_mdct_line_int, tmp;
            Ipp16s max_mdct_line_short;
            Ipp32s mdct_scaleFactor, mdct_scaleFactor1;
            Ipp32s pow34_scaleFact;

            mp3enc_quantIterReset(&state->com, gr, ch);

            mdct_scaleFactor = 0;
            max_mdct_line_int = 0;
            max_mdct_line_short = 0;

            ippsAbs_32s(state->mdct_out_int[gr][ch], mdct_line_abs_int, LEN_MDCT_LINE);
            ippsMax_32s(mdct_line_abs_int, LEN_MDCT_LINE, &max_mdct_line_int);
            while(max_mdct_line_int >= 32768) {
                max_mdct_line_int >>= 1;
                mdct_scaleFactor ++;
            }
            mdct_scaleFactor1 = mdct_scaleFactor;
            tmp = max_mdct_line_int;
            if (tmp)
            while(tmp <= 16383) {
                tmp <<= 1;
                mdct_scaleFactor1 --;
            }

            for (i = 0; i < LEN_MDCT_LINE; i++) {
                mdct_line_abs_short[i] = (Ipp16s)(mdct_line_abs_int[i] >> mdct_scaleFactor);
            }

            max_mdct_line_short = (Ipp16s)max_mdct_line_int;

            pow34_scaleFact = 3 * (mdct_scaleFactor >> 2) - 1;

            if (max_mdct_line_short != 0) {
                Ipp16s tmp_mdct_scaled;
                Ipp32s i_tmp_mdct_scaled;
                ippsPow34_16s_Sfs(&max_mdct_line_short, mdct_scaleFactor,
                    &tmp_mdct_scaled, pow34_scaleFact, 1);
                i_tmp_mdct_scaled = tmp_mdct_scaled;
                while (i_tmp_mdct_scaled <= 16383) {
                    i_tmp_mdct_scaled = i_tmp_mdct_scaled << 1;
                    pow34_scaleFact--;
                }
            }

            ippsPow34_16s_Sfs(mdct_line_abs_short, mdct_scaleFactor,
                mdct_scaled_short, pow34_scaleFact, LEN_MDCT_LINE);

            if (state->com.si_blockType[gr][ch] != 2) {
              pos = 0;
              for (sfb = 0; sfb < state->com.sfb_l_max; sfb++) {
                Ipp32s width = sfb_long[sfb+1] - sfb_long[sfb];
                ippsDotProd_32s_Sfs(&mdct_line_abs_int[pos], &mdct_line_abs_int[pos],
                  width, &mdct_pwr, 2 * mdct_scaleFactor1 + 8);
                ippsMul_32s_Sfs(&mdct_pwr, &state->pa_ratio_l[gr][ch][sfb], &xmin[sfb], 1, 23);
                sfb_last[sfb] = 10000;
                pos += width;
              }
            } else {
              pos = 0;
              for (sfb = 0; sfb < state->com.sfb_s_max; sfb++) {
                Ipp32s width = sfb_short[sfb+1] - sfb_short[sfb];
                for (wnd = 0; wnd < 3; wnd++) {
                ippsDotProd_32s_Sfs(&mdct_line_abs_int[pos], &mdct_line_abs_int[pos],
                  width, &mdct_pwr, 2 * mdct_scaleFactor1 + 8);
                  ippsMul_32s_Sfs(&mdct_pwr, &state->pa_ratio_s[gr][ch][wnd][sfb], &xmin[sfb*3+wnd], 1, 23);
                  sfb_last[sfb*3+wnd] = 10000;
                  pos += width;
                }
              }
            }

            iter = 0;
            last_frame_common_scalefactor = state->last_frame_common_scalefactor[ch];
            do {
              ippsMax_16s(mdct_scaled_short, LEN_MDCT_LINE, &max_mdct_line_short);

              state->start_common_scalefac = -SF_OFFSET;
              state->finish_common_scalefac = -SF_OFFSET;

              if (max_mdct_line_short > 0) {
                  Ipp32s quot = pow34_scaleFact / 3;
                  Ipp32s rem = pow34_scaleFact - quot * 3;
                  Ipp32s shift, max_quant, j, tmp_quot, tmp;
                  Ipp32s delta, add_shift;
                  Ipp16s tmp_buf[16];

                  if (rem > 0) {
                      rem -= 3;
                      quot += 1;
                  }

                  tmp_quot = quot;

                  ippsMulC_16s_Sfs(scalefac_pow, max_mdct_line_short, tmp_buf, 16, 15);

                  shift = 0;
                  max_quant = (MAX_QUANT << (-rem));

                  if (max_quant < (Ipp32s)tmp_buf[0]) {
                      max_quant <<= 3;
                      tmp_quot++;
                  }

                  for (j = 15; j >= 0; j--) {
                      tmp = (Ipp32s)tmp_buf[j];
                      if ((tmp << scalefac_pow_shift[j]) <= max_quant) {
                          shift = j;
                          break;
                      }
                  }

                  state->start_common_scalefac = tmp_quot * 16 - shift - 104;

                  shift = 16;
                  delta = (65536 - MAGIC_NUMBER_I) << (2-rem);

                  tmp = ((Ipp32s)tmp_buf[15] << scalefac_pow_shift[15]);
                  add_shift = 0;

                  while (delta > tmp) {
                      tmp <<= 3;
                      add_shift+=3;
                      quot--;
                  }

                  for (j = 15; j >= 0; j--) {
                      tmp = (Ipp32s)tmp_buf[j];
                      if ((tmp << (scalefac_pow_shift[j] + add_shift)) < delta) {
                          shift = j;
                          break;
                      }
                  }

                  if (shift == 16) {
                      shift = 15;
                      quot++;
                  }

                  state->finish_common_scalefac = (quot + 6) * 16 - shift + 1 - 104;

                  if (state->start_common_scalefac > 255 - SF_OFFSET) {
                      state->start_common_scalefac = 255 - SF_OFFSET;
                  } else if (state->start_common_scalefac < -SF_OFFSET) {
                      state->start_common_scalefac = -SF_OFFSET;
                  }

                  if (state->finish_common_scalefac > 255 - SF_OFFSET) {
                      state->finish_common_scalefac = 255 - SF_OFFSET;
                  } else if (state->finish_common_scalefac < -SF_OFFSET) {
                      state->finish_common_scalefac = -SF_OFFSET;
                  }
              }

              mp3ienc_quantMainLoop(state,
                  gr, ch, mdct_scaled_short, pow34_scaleFact);

              state->common_scalefactor_update[ch] = 2;

              if (state->com.ns_mode == 0)
                break;
            } while(iter++ < QUANT_ITER_NUM &&
              mp3ienc_AdjustSF(state, xmin, distortion, sfb_last, gr, ch, mdct_scaleFactor1, &pow34_scaleFact));

            state->common_scalefactor_update[ch] = state->com.si_globGain[gr][ch] - SF_OFFSET -
              last_frame_common_scalefactor;

            if (state->common_scalefactor_update[ch] >= 0) {
              if (state->common_scalefactor_update[ch] <= 2)
                state->common_scalefactor_update[ch] = 2;
            } else {
              if (state->common_scalefactor_update[ch] >= -2)
                state->common_scalefactor_update[ch] = -2;
            }
            state->com.frameBits += state->com.si_part2Len[gr][ch];
            state->com.frameBits += state->com.si_part23Len[gr][ch];
        }
    }
    if (state->com.br_mode == MPAENC_ABR) {
      state->com.header.bitRate =
        mp3encGEBitrate(&state->com, ((state->com.frameBits + 7) >> 3) - state->com.si_main_data_begin);
    }
    return 1;
}

void mp3ienc_quantMainLoop(MP3Enc *state,
                           Ipp32s gr, Ipp32s ch,
                           Ipp16s *mdct_scaled_short,
                           Ipp32s pow34_scaleFact)
{
    Ipp16s tmp_x_quant_short[LEN_MDCT_LINE];
    Ipp32s index, scale, shift;
    Ipp32s magic_number;

    Ipp32s common_scalefactor;
    Ipp32s needed_bits;

    common_scalefactor = state->last_frame_common_scalefactor[ch];
//    state->common_scalefactor_update[ch] = state->common_scalefactor_update[ch];

    if (common_scalefactor < state->start_common_scalefac)
        common_scalefactor = state->start_common_scalefac;

    if (common_scalefactor > state->finish_common_scalefac)
        common_scalefactor = state->finish_common_scalefac;
    for(;;) {
        index = (-(common_scalefactor + 104)) & 0xF;
        scale = pow34_scaleFact +
            (3 * ((-(common_scalefactor + 104)) >> 4) + scalefac_pow_shift[index]);

        magic_number = (Ipp32s)MAGIC_NUMBER_I - 32768;

        shift = scale + 16;
        if (scale >= 0) magic_number = 0;
        else if (scale > -16) {
            magic_number = ((magic_number + (1 << (shift - 1))) >> shift);
            shift = 0;
        } else if (scale < -16) {
            shift = -shift;
            scale = -16;
        }

        ippsMulC_16s_Sfs(mdct_scaled_short, scalefac_pow[index], tmp_x_quant_short,
            LEN_MDCT_LINE, 15 + shift);

        ippsAddC_16s_Sfs(tmp_x_quant_short, (Ipp16s)magic_number, state->com.quant_ix[gr][ch],
            LEN_MDCT_LINE, -scale);

        needed_bits = mp3enc_quantCalcBits(&state->com, gr, ch);

        if (needed_bits == state->com.max_bits[gr][ch])
            break;

        if (needed_bits > state->com.max_bits[gr][ch]) {
            if (common_scalefactor == state->finish_common_scalefac)
                break;

            if (state->common_scalefactor_update[ch] < 0) {
                state->common_scalefactor_update[ch] = -state->common_scalefactor_update[ch];
            }
            state->common_scalefactor_update[ch] = (state->common_scalefactor_update[ch] + 1) >> 1;
        } else {
            if (common_scalefactor == state->start_common_scalefac)
                break;

            if (state->common_scalefactor_update[ch] == 1)
                break;

            if (state->common_scalefactor_update[ch] > 0) {
                state->common_scalefactor_update[ch] = -state->common_scalefactor_update[ch];
            }
            state->common_scalefactor_update[ch] >>= 1;
        }

        common_scalefactor += state->common_scalefactor_update[ch];

        if (common_scalefactor < state->start_common_scalefac)
            common_scalefactor = state->start_common_scalefac;

        if (common_scalefactor > state->finish_common_scalefac)
            common_scalefactor = state->finish_common_scalefac;
    }

    state->common_scalefactor_update[ch] =
        common_scalefactor - state->last_frame_common_scalefactor[ch];
    state->last_frame_common_scalefactor[ch] = common_scalefactor;

    if (state->common_scalefactor_update[ch] >= 0) {
        if (state->common_scalefactor_update[ch] <= 2)
            state->common_scalefactor_update[ch] = 2;
    } else {
        if (state->common_scalefactor_update[ch] >= -2)
            state->common_scalefactor_update[ch] = -2;
    }

    state->com.si_globGain[gr][ch] = (Ipp16s)(common_scalefactor + SF_OFFSET);

    state->com.si_part23Len[gr][ch] = needed_bits;
}

#endif //UMC_ENABLE_MP3_INT_AUDIO_ENCODER
